<script lang="ts">
  import {
    AlignEndHorizontal,
    AlignEndVertical,
    AlignStartHorizontal,
    AlignStartVertical,
    Expand,
    Shrink,
  } from "lucide-svelte";
  import { drawStore } from "../store.svelte";
  import {
    update_node_position,
    update_node_size,
    update_node_style,
    type ExDrawNodeInfo,
  } from "$lib/api/board/board_draw";
  import { get_user_session } from "$lib/api/user";
  import { request } from "$lib/utils/request";

  let hasChange = $state(false);

  let layer = $state(-1);

  function alignLeft() {
    let left: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (left == null) {
        left = node.x;
      } else {
        if (node.x < left) {
          left = node.x;
        }
      }
    }
    if (left == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.x = left;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  function alignTop() {
    let top: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (top == null) {
        top = node.y;
      } else {
        if (node.y < top) {
          top = node.y;
        }
      }
    }
    if (top == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.y = top;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  function alignRight() {
    let right: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (right == null) {
        right = node.x + node.w;
      } else {
        if (node.x + node.w > right) {
          right = node.x + node.w;
        }
      }
    }
    if (right == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.x = right - node.w;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  function alignBottom() {
    let bottom: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (bottom == null) {
        bottom = node.y + node.h;
      } else {
        if (node.y + node.h > bottom) {
          bottom = node.y + node.h;
        }
      }
    }
    if (bottom == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.y = bottom - node.h;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  function shrinkSize() {
    let minW: null | number = null;
    let minH: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (minW == null) {
        minW = node.w;
      } else if (minW > node.w) {
        minW = node.w;
      }
      if (minH == null) {
        minH = node.h;
      } else if (minH > node.h) {
        minH = node.h;
      }
    }
    if (minW == null || minH == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.w = minW;
        node.h = minH;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  function expandSize() {
    let maxW: null | number = null;
    let maxH: null | number = null;
    for (const node of drawStore.nodeList) {
      if (!drawStore.selectNodeIdList.includes(node.node_id)) {
        continue;
      }
      if (maxW == null) {
        maxW = node.w;
      } else if (maxW < node.w) {
        maxW = node.w;
      }
      if (maxH == null) {
        maxH = node.h;
      } else if (maxH < node.h) {
        maxH = node.h;
      }
    }
    if (maxW == null || maxH == null) {
      return;
    }
    hasChange = true;

    const newNodeList = [] as ExDrawNodeInfo[];
    for (const node of drawStore.nodeList) {
      if (drawStore.selectNodeIdList.includes(node.node_id)) {
        node.w = maxW;
        node.h = maxH;
      }
      newNodeList.push(node);
    }
    drawStore.nodeList = newNodeList;
  }

  async function saveNodeList() {
    const saveNodeList = drawStore.nodeList
      .filter((item) => drawStore.selectNodeIdList.includes(item.node_id))
      .slice();
    const sessionId = await get_user_session();
    for (const node of saveNodeList) {
      await request(
        update_node_position({
          session_id: sessionId,
          board_id: drawStore.boardInfo?.board_id ?? "",
          draw_id: drawStore.drawId,
          node_id: node.node_id,
          x: node.x,
          y: node.y,
        }),
      );
      await request(
        update_node_size({
          session_id: sessionId,
          board_id: drawStore.boardInfo?.board_id ?? "",
          draw_id: drawStore.drawId,
          node_id: node.node_id,
          w: node.w,
          h: node.h,
        }),
      );
      if (layer != -1) {
        update_node_style({
          session_id: sessionId,
          board_id: drawStore.boardInfo?.board_id ?? "",
          draw_id: drawStore.drawId,
          node_id: node.node_id,
          node_style: {
            ...node.node_style,
            layer: layer,
          },
        });
      }
    }
    hasChange = false;
  }

  $effect(() => {
    return () => {
      if (hasChange) {
        drawStore.loadNodeList();
      }
    };
  });
</script>

<div class="bg-surface-200-800 w-[220px] p-4">
  <label class="label">
    <span class="label-text">图层</span>
    <select
      class="select rounded-none bg-surface-100-900"
      value={layer}
      onchange={(e) => {
        hasChange = true;
        layer = parseInt(e.currentTarget.value);
        if (layer != -1) {
          const newNodeList = [] as ExDrawNodeInfo[];
          for (const node of drawStore.nodeList) {
            if (drawStore.selectNodeIdList.includes(node.node_id)) {
              node.node_style.layer = layer;
            }
            newNodeList.push(node);
          }
          drawStore.nodeList = newNodeList;
        }
      }}
    >
      <option value={-1}>保持不变</option>
      <option value={0}>0</option>
      <option value={1}>1</option>
      <option value={2}>2</option>
      <option value={3}>3</option>
      <option value={4}>4</option>
      <option value={5}>5</option>
      <option value={6}>6</option>
      <option value={7}>7</option>
      <option value={8}>8</option>
      <option value={9}>9</option>
    </select>
  </label>
  <h4 class="h4">对齐</h4>
  <div class="flex gap-2">
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="左对齐"
      onclick={() => alignLeft()}
    >
      <AlignStartVertical />
    </button>
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="顶部对齐"
      onclick={() => alignTop()}
    >
      <AlignStartHorizontal />
    </button>
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="右对齐"
      onclick={() => alignRight()}
    >
      <AlignEndVertical />
    </button>
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="底部对齐"
      onclick={() => alignBottom()}
    >
      <AlignEndHorizontal />
    </button>
  </div>
  <h4 class="h4">大小</h4>
  <div class="flex gap-2">
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="最小宽度和高度"
      onclick={() => shrinkSize()}
    >
      <Shrink />
    </button>
    <button
      type="button"
      class="btn bg-surface-300-700 text-primary-900-100 p-2"
      title="最大宽度和高度"
      onclick={() => expandSize()}
    >
      <Expand />
    </button>
  </div>

  {#if hasChange}
    <footer class="flex justify-end gap-4 mt-2">
      <button
        type="button"
        class="btn preset-tonal"
        onclick={() => {
          drawStore.loadNodeList();
          hasChange = false;
        }}>重置</button
      >
      <button
        type="button"
        class="btn preset-filled-primary-900-100"
        onclick={() => saveNodeList()}
      >
        保存
      </button>
    </footer>
  {/if}
</div>
